home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / dev / gcc / ixemul_src.lha / ixemul-41.0 / network / gethostnamadr.c < prev    next >
C/C++ Source or Header  |  1995-05-18  |  10KB  |  434 lines

  1. /*
  2.  * Copyright (c) 1985, 1988 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #if defined(LIBC_SCCS) && !defined(lint)
  35. static char sccsid[] = "@(#)gethostnamadr.c    6.45 (Berkeley) 2/24/91";
  36. #endif /* LIBC_SCCS and not lint */
  37.  
  38. #include <sys/param.h>
  39. #include <sys/socket.h>
  40. #include <netinet/in.h>
  41. #include <arpa/inet.h>
  42. #include <arpa/nameser.h>
  43. #include <netdb.h>
  44. #include <resolv.h>
  45. #include <stdio.h>
  46. #include <ctype.h>
  47. #include <errno.h>
  48. #include <string.h>
  49.  
  50. #define    MAXALIASES    35
  51. #define    MAXADDRS    35
  52.  
  53. static char *h_addr_ptrs[MAXADDRS + 1];
  54.  
  55. static struct hostent host;
  56. static char *host_aliases[MAXALIASES];
  57. static char hostbuf[BUFSIZ+1];
  58. static struct in_addr host_addr;
  59. static FILE *hostf = NULL;
  60. static char hostaddr[MAXADDRS];
  61. static char *host_addrs[2];
  62. static int stayopen = 0;
  63. char *strpbrk();
  64.  
  65. #if PACKETSZ > 1024
  66. #define    MAXPACKET    PACKETSZ
  67. #else
  68. #define    MAXPACKET    1024
  69. #endif
  70.  
  71. typedef union {
  72.     HEADER hdr;
  73.     u_char buf[MAXPACKET];
  74. } querybuf;
  75.  
  76. typedef union {
  77.     long al;
  78.     char ac;
  79. } align;
  80.  
  81. int h_errno;
  82.  
  83. static struct hostent *
  84. getanswer(answer, anslen, iquery)
  85.     querybuf *answer;
  86.     int anslen;
  87.     int iquery;
  88. {
  89.     register HEADER *hp;
  90.     register u_char *cp;
  91.     register int n;
  92.     u_char *eom;
  93.     char *bp, **ap;
  94.     int type, class, buflen, ancount, qdcount;
  95.     int haveanswer, getclass = C_ANY;
  96.     char **hap;
  97.  
  98.     eom = answer->buf + anslen;
  99.     /*
  100.      * find first satisfactory answer
  101.      */
  102.     hp = &answer->hdr;
  103.     ancount = ntohs(hp->ancount);
  104.     qdcount = ntohs(hp->qdcount);
  105.     bp = hostbuf;
  106.     buflen = sizeof(hostbuf);
  107.     cp = answer->buf + sizeof(HEADER);
  108.     if (qdcount) {
  109.         if (iquery) {
  110.             if ((n = dn_expand((u_char *)answer->buf,
  111.                 (u_char *)eom, (u_char *)cp, (u_char *)bp,
  112.                 buflen)) < 0) {
  113.                 h_errno = NO_RECOVERY;
  114.                 return ((struct hostent *) NULL);
  115.             }
  116.             cp += n + QFIXEDSZ;
  117.             host.h_name = bp;
  118.             n = strlen(bp) + 1;
  119.             bp += n;
  120.             buflen -= n;
  121.         } else
  122.             cp += __dn_skipname(cp, eom) + QFIXEDSZ;
  123.         while (--qdcount > 0)
  124.             cp += __dn_skipname(cp, eom) + QFIXEDSZ;
  125.     } else if (iquery) {
  126.         if (hp->aa)
  127.             h_errno = HOST_NOT_FOUND;
  128.         else
  129.             h_errno = TRY_AGAIN;
  130.         return ((struct hostent *) NULL);
  131.     }
  132.     ap = host_aliases;
  133.     *ap = NULL;
  134.     host.h_aliases = host_aliases;
  135.     hap = h_addr_ptrs;
  136.     *hap = NULL;
  137. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  138.     host.h_addr_list = h_addr_ptrs;
  139. #endif
  140.     haveanswer = 0;
  141.     while (--ancount >= 0 && cp < eom) {
  142.         if ((n = dn_expand((u_char *)answer->buf, (u_char *)eom,
  143.             (u_char *)cp, (u_char *)bp, buflen)) < 0)
  144.             break;
  145.         cp += n;
  146.         type = _getshort(cp);
  147.          cp += sizeof(u_short);
  148.         class = _getshort(cp);
  149.          cp += sizeof(u_short) + sizeof(u_long);
  150.         n = _getshort(cp);
  151.         cp += sizeof(u_short);
  152.         if (type == T_CNAME) {
  153.             cp += n;
  154.             if (ap >= &host_aliases[MAXALIASES-1])
  155.                 continue;
  156.             *ap++ = bp;
  157.             n = strlen(bp) + 1;
  158.             bp += n;
  159.             buflen -= n;
  160.             continue;
  161.         }
  162.         if (iquery && type == T_PTR) {
  163.             if ((n = dn_expand((u_char *)answer->buf,
  164.                 (u_char *)eom, (u_char *)cp, (u_char *)bp,
  165.                 buflen)) < 0) {
  166.                 cp += n;
  167.                 continue;
  168.             }
  169.             cp += n;
  170.             host.h_name = bp;
  171.             return(&host);
  172.         }
  173.         if (iquery || type != T_A)  {
  174. #ifdef DEBUG
  175.             if (_res.options & RES_DEBUG)
  176.                 printf("unexpected answer type %d, size %d\n",
  177.                     type, n);
  178. #endif
  179.             cp += n;
  180.             continue;
  181.         }
  182.         if (haveanswer) {
  183.             if (n != host.h_length) {
  184.                 cp += n;
  185.                 continue;
  186.             }
  187.             if (class != getclass) {
  188.                 cp += n;
  189.                 continue;
  190.             }
  191.         } else {
  192.             host.h_length = n;
  193.             getclass = class;
  194.             host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC;
  195.             if (!iquery) {
  196.                 host.h_name = bp;
  197.                 bp += strlen(bp) + 1;
  198.             }
  199.         }
  200.  
  201.         bp += sizeof(align) - ((u_long)bp % sizeof(align));
  202.  
  203.         if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
  204. #ifdef DEBUG
  205.             if (_res.options & RES_DEBUG)
  206.                 printf("size (%d) too big\n", n);
  207. #endif
  208.             break;
  209.         }
  210.         bcopy(cp, *hap++ = bp, n);
  211.         bp +=n;
  212.         cp += n;
  213.         haveanswer++;
  214.     }
  215.     if (haveanswer) {
  216.         *ap = NULL;
  217. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  218.         *hap = NULL;
  219. #else
  220.         host.h_addr = h_addr_ptrs[0];
  221. #endif
  222.         return (&host);
  223.     } else {
  224.         h_errno = TRY_AGAIN;
  225.         return ((struct hostent *) NULL);
  226.     }
  227. }
  228.  
  229. struct hostent *
  230. gethostbyname(name)
  231.     char *name;
  232. {
  233.     querybuf buf;
  234.     register char *cp;
  235.     int n;
  236.     extern struct hostent *_gethtbyname();
  237.  
  238.     /*
  239.      * disallow names consisting only of digits/dots, unless
  240.      * they end in a dot.
  241.      */
  242.     if (isdigit(name[0]))
  243.         for (cp = name;; ++cp) {
  244.             if (!*cp) {
  245.                 if (*--cp == '.')
  246.                     break;
  247.                 /*
  248.                  * All-numeric, no dot at the end.
  249.                  * Fake up a hostent as if we'd actually
  250.                  * done a lookup.  What if someone types
  251.                  * 255.255.255.255?  The test below will
  252.                  * succeed spuriously... ???
  253.                  */
  254.                 if ((host_addr.s_addr = inet_addr(name)) == -1) {
  255.                     h_errno = HOST_NOT_FOUND;
  256.                     return((struct hostent *) NULL);
  257.                 }
  258.                 host.h_name = name;
  259.                 host.h_aliases = host_aliases;
  260.                 host_aliases[0] = NULL;
  261.                 host.h_addrtype = AF_INET;
  262.                 host.h_length = sizeof(u_long);
  263.                 h_addr_ptrs[0] = (char *)&host_addr;
  264.                 h_addr_ptrs[1] = (char *)0;
  265. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  266.                 host.h_addr_list = h_addr_ptrs;
  267. #else
  268.                 host.h_addr = h_addr_ptrs[0];
  269. #endif
  270.                 return (&host);
  271.             }
  272.             if (!isdigit(*cp) && *cp != '.') 
  273.                 break;
  274.         }
  275.  
  276.     if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) {
  277. #ifdef DEBUG
  278.         if (_res.options & RES_DEBUG)
  279.             printf("res_search failed\n");
  280. #endif
  281.         if (errno == ECONNREFUSED)
  282.             return (_gethtbyname(name));
  283.         else
  284.             return ((struct hostent *) NULL);
  285.     }
  286.     return (getanswer(&buf, n, 0));
  287. }
  288.  
  289. struct hostent *
  290. gethostbyaddr(addr, len, type)
  291.     const char *addr;
  292.     int len, type;
  293. {
  294.     int n;
  295.     querybuf buf;
  296.     register struct hostent *hp;
  297.     char qbuf[MAXDNAME];
  298.     extern struct hostent *_gethtbyaddr();
  299.     
  300.     if (type != AF_INET)
  301.         return ((struct hostent *) NULL);
  302.     (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
  303.         ((unsigned)addr[3] & 0xff),
  304.         ((unsigned)addr[2] & 0xff),
  305.         ((unsigned)addr[1] & 0xff),
  306.         ((unsigned)addr[0] & 0xff));
  307.     n = res_query(qbuf, C_IN, T_PTR, (char *)&buf, sizeof(buf));
  308.     if (n < 0) {
  309. #ifdef DEBUG
  310.         if (_res.options & RES_DEBUG)
  311.             printf("res_query failed\n");
  312. #endif
  313.         if (errno == ECONNREFUSED)
  314.             return (_gethtbyaddr(addr, len, type));
  315.         return ((struct hostent *) NULL);
  316.     }
  317.     hp = getanswer(&buf, n, 1);
  318.     if (hp == NULL)
  319.         return ((struct hostent *) NULL);
  320.     hp->h_addrtype = type;
  321.     hp->h_length = len;
  322.     h_addr_ptrs[0] = (char *)&host_addr;
  323.     h_addr_ptrs[1] = (char *)0;
  324.     host_addr = *(struct in_addr *)addr;
  325. #if BSD < 43 && !defined(h_addr)    /* new-style hostent structure */
  326.     hp->h_addr = h_addr_ptrs[0];
  327. #endif
  328.     return(hp);
  329. }
  330.  
  331. _sethtent(f)
  332.     int f;
  333. {
  334.     if (hostf == NULL)
  335.         hostf = fopen(_PATH_HOSTS, "r" );
  336.     else
  337.         rewind(hostf);
  338.     stayopen |= f;
  339. }
  340.  
  341. _endhtent()
  342. {
  343.     if (hostf && !stayopen) {
  344.         (void) fclose(hostf);
  345.         hostf = NULL;
  346.     }
  347. }
  348.  
  349. struct hostent *
  350. _gethtent()
  351. {
  352.     char *p;
  353.     register char *cp, **q;
  354.  
  355.     if (hostf == NULL && (hostf = fopen(_PATH_HOSTS, "r" )) == NULL)
  356.         return (NULL);
  357. again:
  358.     if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL)
  359.         return (NULL);
  360.     if (*p == '#')
  361.         goto again;
  362.     cp = strpbrk(p, "#\n");
  363.     if (cp == NULL)
  364.         goto again;
  365.     *cp = '\0';
  366.     cp = strpbrk(p, " \t");
  367.     if (cp == NULL)
  368.         goto again;
  369.     *cp++ = '\0';
  370.     /* THIS STUFF IS INTERNET SPECIFIC */
  371. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  372.     host.h_addr_list = host_addrs;
  373. #endif
  374.     host.h_addr = hostaddr;
  375.     *((u_long *)host.h_addr) = inet_addr(p);
  376.     host.h_length = sizeof (u_long);
  377.     host.h_addrtype = AF_INET;
  378.     while (*cp == ' ' || *cp == '\t')
  379.         cp++;
  380.     host.h_name = cp;
  381.     q = host.h_aliases = host_aliases;
  382.     cp = strpbrk(cp, " \t");
  383.     if (cp != NULL) 
  384.         *cp++ = '\0';
  385.     while (cp && *cp) {
  386.         if (*cp == ' ' || *cp == '\t') {
  387.             cp++;
  388.             continue;
  389.         }
  390.         if (q < &host_aliases[MAXALIASES - 1])
  391.             *q++ = cp;
  392.         cp = strpbrk(cp, " \t");
  393.         if (cp != NULL)
  394.             *cp++ = '\0';
  395.     }
  396.     *q = NULL;
  397.     return (&host);
  398. }
  399.  
  400. struct hostent *
  401. _gethtbyname(name)
  402.     char *name;
  403. {
  404.     register struct hostent *p;
  405.     register char **cp;
  406.     
  407.     _sethtent(0);
  408.     while (p = _gethtent()) {
  409.         if (strcasecmp(p->h_name, name) == 0)
  410.             break;
  411.         for (cp = p->h_aliases; *cp != 0; cp++)
  412.             if (strcasecmp(*cp, name) == 0)
  413.                 goto found;
  414.     }
  415. found:
  416.     _endhtent();
  417.     return (p);
  418. }
  419.  
  420. struct hostent *
  421. _gethtbyaddr(addr, len, type)
  422.     const char *addr;
  423.     int len, type;
  424. {
  425.     register struct hostent *p;
  426.  
  427.     _sethtent(0);
  428.     while (p = _gethtent())
  429.         if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len))
  430.             break;
  431.     _endhtent();
  432.     return (p);
  433. }
  434.